package rcs34.android.Namedays.Activity;

import java.util.ArrayList;
import java.util.GregorianCalendar;

import rcs34.android.Namedays.DBHelper;
import rcs34.android.Namedays.GApp;
import rcs34.android.Namedays.Oneday;
import rcs34.android.Namedays.R;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.TextView;

public class NamedaysAdapter extends BaseAdapter implements ListAdapter,
    Filterable {
	public final static int DAYS_IN_YEAR = 366;
	private ArrayList<Oneday> filtered = new ArrayList<Oneday>();
	private ArrayList<Oneday> cache = null;
	private A_Namedays activity = null;
	private Activity activityContext;
	// private boolean notifyActivity = false;
	private NamedaysFilter filter = new NamedaysFilter();
	private String sFilter = "";

	private class ViewHolder {
		public ImageView mark;
		public TextView date;
		public TextView name;
	}

	private class Populator extends AsyncTask<String, Integer, ArrayList<Oneday>> {
		@Override
		protected void onPreExecute() {
			if (activity != null) {
				activity.setProgress(0);
			}
		}

		@Override
		protected ArrayList<Oneday> doInBackground(String... _param) {
			String table = _param[0];
			boolean supportHtml = (table.equals(GApp.tableCZ));
			ArrayList<Oneday> tmpCache;
			GregorianCalendar now = new GregorianCalendar();
			int year = now.get(GregorianCalendar.YEAR);
			GApp.isALeepYear = now.isLeapYear(year);
			if (cache == null) {
				// To see the 02.29.'s Names, but not in the HU and RU
				if (!table.equals(GApp.tableHU) && !table.equals(GApp.tableRU)) {
					while (!now.isLeapYear(year)) {
						year++;
					}
				}
				GregorianCalendar aDay = new GregorianCalendar(year, 0, 1, 0, 1);
				tmpCache = new ArrayList<Oneday>();
				DBHelper dbHelper = new DBHelper(table);
				SQLiteDatabase db = dbHelper.getReadableDatabase();
				GregorianCalendar today=new GregorianCalendar();
				for (int i = 0; i < DAYS_IN_YEAR; i++) {
					Cursor cursor = dbHelper.findByDate(db, aDay);
					cursor.moveToFirst();
					Oneday newDay = new Oneday(aDay, supportHtml);
					while (!cursor.isAfterLast()) {
						newDay.addName(cursor.getString(0));
						cursor.moveToNext();
					}
					cursor.close();
					tmpCache.add(newDay);
					if(aDay.get(GregorianCalendar.DAY_OF_YEAR)==today.get(GregorianCalendar.DAY_OF_YEAR) 
							&& aDay.get(GregorianCalendar.MONTH)==today.get(GregorianCalendar.MONTH)){
						GApp.setPosition(i);
					}
					aDay.add(GregorianCalendar.DAY_OF_YEAR, 1);
					if (i % 10 == 0) {
						publishProgress(i);
					}
				}
				db.close();
			} else {
				tmpCache = cache;
			}
			return tmpCache;
		}

		protected void onProgressUpdate(Integer... _progress) {
			if (activity != null) {
				activity.setProgress((_progress[0] * 10000) / DAYS_IN_YEAR);
			}
		}

		protected void onPostExecute(ArrayList<Oneday> result) {
			cache = result;
			if (activity != null) {
				activity.setProgress(10000);
				activity.notifyPopulated();
			}
		}
	}

	public NamedaysAdapter(Activity _context, String _table) {
		activity = (A_Namedays) _context;
		activityContext = _context;
		Populator populator = new Populator();
		populator.execute(_table);
	}

	public void setActivity(A_Namedays _activity) {
		activity = _activity;
	}

	public void cancelFilter() {
		filtered = cache;
		notifyDataSetChanged();
	}

	public View getView(int _position, View _convertView, ViewGroup _parent) {
    View result = _convertView;
    if (result == null) {
      LayoutInflater inflater = activityContext.getLayoutInflater();
      result = inflater.inflate(R.layout.activityday, null);
      ViewHolder viewHolder = new ViewHolder();
      viewHolder.mark = (ImageView) result.findViewById(R.id.a_mark);
      viewHolder.date = (TextView) result.findViewById(R.id.a_date);
      viewHolder.name = (TextView) result.findViewById(R.id.a_name);
      viewHolder.name.setMovementMethod(LinkMovementMethod.getInstance());
      result.setTag(viewHolder);
    }
    Oneday oneday=filtered.get(_position);
    String date;
    if(GApp.mmddDate){
    	date=(oneday.getMonth()+1)+"."+oneday.getDay()+".";
    }else{
    	date=oneday.getDay()+"."+(oneday.getMonth()+1)+".";
    }
    ViewHolder holder = (ViewHolder) result.getTag();
    holder.date.setText(date);
    holder.name.setText(oneday.getHtmlNames());
    if (isToday(oneday)) {
      holder.mark.setImageResource(R.drawable.mark_nameday);
    } else {
      holder.mark.setImageResource(R.drawable.mark_empty);
    }
    return result;
  }

	private boolean isToday(Oneday _oneday) {
		return (_oneday.getDay() == activity.today
		    .get(GregorianCalendar.DAY_OF_MONTH) && _oneday.getMonth() == activity.today
		    .get(GregorianCalendar.MONTH));
	}

	public int getCount() {
		/*
		 * if (notifyActivity && filtered.size() >= DAYS_IN_YEAR) { notifyActivity =
		 * false; activity.notifyFilterPublished(); }
		 */
		return filtered.size();
	}

	public Object getItem(int _position) {
		return filtered.get(_position);
	}

	public long getItemId(int _position) {
		return filtered.get(_position).hashCode();
	}

	public int getItemViewType(int _position) {
		Oneday oneday = filtered.get(_position);
		if (isToday(oneday)) {
			return 1;
		} else {
			return 0;
		}
	}

	public int getViewTypeCount() {
		return 2;
	}

	public boolean hasStableIds() {
		return true;
	}

	public boolean isEmpty() {
		return filtered.isEmpty();
	}

	public boolean areAllItemsEnabled() {
		return true;
	}

	public boolean isEnabled(int position) {
		return true;
	}

	public Filter getFilter() {
		return filter;
	}

	public String getSFilter() {
		return sFilter;
	}

	private class NamedaysFilter extends Filter {
		@Override
		protected FilterResults performFiltering(CharSequence _constraint) {
			FilterResults retval = null;
			if (cache != null) {
				retval = new FilterResults();
				retval.values = cache;
				retval.count = cache.size();
				sFilter = null;
				if (_constraint != null && _constraint.length() > 0) {
					sFilter = _constraint.toString();
					ArrayList<Oneday> tmpRetval = new ArrayList<Oneday>();
					for (int i = 0; i < cache.size(); i++) {
						Oneday day = cache.get(i);
						if (day.startsWith(sFilter)) {
							tmpRetval.add(day);
						}
					}
					retval.values = tmpRetval;
					retval.count = tmpRetval.size();
				}
			}
			return retval;
		}

		@SuppressWarnings("unchecked")
		@Override
		protected void publishResults(CharSequence constraint, FilterResults results) {
			if (results != null) {
				filtered = (ArrayList<Oneday>) results.values;
				notifyDataSetChanged();
				// notifyActivity = true;
			}
		}
	}
}
